﻿#region Header

/*
Remote views based on linq
By

Pascal Hauser 
Dipl. Ing. in Informatik, Hochschule für Technik Rapperswil, 2006
Master Thesis, Hochschule für Technik Rapperswil, 2008-2010

and

Raphael Gfeller
Dipl. Ing. in Informatik, Hochschule für Technik Rapperswil, 2006
Master Thesis, Hochschule für Technik Rapperswil, 2008-2010

*/

#endregion

#region Usings

using System;
using Sebarf.Core.Interfaces;
using Sebarf.Core.Internal;
using Sebarf.Diagnostics.Interfaces;
using Sebarf.Security.Interfaces;

#endregion

namespace Sebarf.Core {
	/// <summary>
	/// Description of the class
	/// </summary>
	public class RequestHandlerEngine : IRequestHandlerEngineImpl {
		#region Public Properties

		public IRequestHandler[] ApplicationHandlers {
			get { return m_applicationHandlers; }
		}

		public IRequestHandler[] InternalHandlers {
			get { return m_internalHandlers; }
		}

		#endregion

		#region Public Methods

		/// <summary>
		/// process the request
		/// </summary>
		/// <param name="request"></param>
		/// <returns></returns>
		/// <exception cref="NotSupportedException">if no handler is available</exception>
		public object Process(IRequest request) {
			try {
				Check.AssertException(
					m_locator == null || m_locator.GetRegisteredServices<IAuthenticationManagementService>().Length <= 1,
					"not more than one IAuthenticationManagementService is allowed");
				Logger.WriteDebug("receive request: " + request);
				// internal can used by everyone
				foreach (IRequestHandler handler in m_internalHandlers) {
					if (handler.CanHandleRequest(request)) {
						Logger.WriteDebug("process request: " + request);
						object toReturn = handler.ProcessRequest(request, m_locator);
						Logger.WriteDebug("request " + request + " has been processed");
						return toReturn;
					}
				}
				if ((m_locator == null || !m_locator.IsServiceAvailable<IAuthenticationManagementService>() ||
					 m_locator.GetRegisteredService<IAuthenticationManagementService>().IsAuthenticated())) {
					foreach (IRequestHandler handler in m_applicationHandlers) {
						if (handler.CanHandleRequest(request)) {
							Logger.WriteDebug("process request: " + request);
							object toReturn = handler.ProcessRequest(request, m_locator);
							Logger.WriteDebug("request " + request + " has been processed");
							return toReturn;
						}
					}
					Logger.WriteInformation("no handler for request:" + request + " is available");
					return new UnableToProcessRequestReturnValue { UnableToProcessRequestReason = UnableToProcessRequestReturnValue.Reason.NotSupported };
				}
				else {
					return new UnableToProcessRequestReturnValue { UnableToProcessRequestReason = UnableToProcessRequestReturnValue.Reason.Security };
				}
			}
			catch (Exception) {
				return new UnableToProcessRequestReturnValue { UnableToProcessRequestReason = UnableToProcessRequestReturnValue.Reason.Unknown };
			}
		}

		public static RequestHandlerEngine Create(IServiceLocatorService locator, IRequestHandler[] applicationHandlers,
												   IRequestHandler[] internalHandlers) {
			var toReturn = new RequestHandlerEngine();
			toReturn.m_applicationHandlers = applicationHandlers;
			toReturn.m_locator = locator;
			toReturn.m_internalHandlers = internalHandlers;
			if (locator != null) {
				locator.GetRegisteredService<IServiceRegistrationService>().RegisterService(
					new RequestHandlerEngineLocatorService(toReturn));
				locator.GetRegisteredService<IServiceRegistrationService>().RegisterService(new AddRequestHandlerService(toReturn));
				locator.GetRegisteredService<IServiceRegistrationService>().RegisterService(locator);
			}
			else {
				Logger.WriteWarning("for using the serviceLocatorService, please submitt a valid instance");
			}
			return toReturn;
		}

		public static RequestHandlerEngine Create(IServiceLocatorService locator, IRequestHandler[] handlers) {
			return Create(locator, new IRequestHandler[] { }, handlers);
		}

		public void SetHandler(IRequestHandler[] handlers) {
			m_applicationHandlers = handlers;
		}

		#endregion

		#region Private Methods

		private RequestHandlerEngine() {
		}

		#endregion

		#region Private Fields

		private IRequestHandler[] m_applicationHandlers;
		private IRequestHandler[] m_internalHandlers;
		private IServiceLocatorService m_locator;

		#endregion

		#region IRequestHandlerEngineImpl Members

		public void Dispose() {
			Logger.WriteInformation("Close session");
			// todo: clean up
		}

		public IServiceLocatorService ServiceLocatorService {
			get { return m_locator; }
			set { m_locator = value; }
		}

		#endregion
	}
}